﻿/*  
	========================================================================
	 awzBoxes Library
	
	 Homepage: http://www.awzhome.de/
	========================================================================
	
	This Source Code Form is subject to the terms of the Mozilla Public
	License, v. 2.0. If a copy of the MPL was not distributed with this
	file, You can obtain one at http://mozilla.org/MPL/2.0/.
   
	The Original Code is code of awzBoxes Library.

	The Initial Developer of the Original Code is Andreas Weizel.
	Portions created by the Initial Developer are
	Copyright (C) 2011-2012 Andreas Weizel. All Rights Reserved.
	
	Contributor(s): (none)
	
	========================================================================
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows;
using System.ComponentModel;
using AWZhome.awzBoxes.Tools;

namespace AWZhome.awzBoxes
{
	/// <summary>
	/// Represents a single window (tab) in the <see cref="AWZhome.awzBoxes.Box"/>.
	/// </summary>
	[ContentProperty("Content")]
	public class BoxItem : DependencyObject
	{
		private Box _parentBox = null;
		private AutoHiddenBox _parentAutoHiddenBox = null;
		private FloatingWindow _parentFloatingWindow = null;
		private BoxItemDockDirection _direction;

		#region Dependency properties

		public static readonly DependencyProperty IconProperty =
			DependencyProperty.Register("Icon", typeof(System.Windows.Media.ImageSource), typeof(BoxItem), new UIPropertyMetadata(null));
		public static readonly DependencyProperty TitleProperty =
			DependencyProperty.Register("Title", typeof(string), typeof(BoxItem), new UIPropertyMetadata(null));
		public static readonly DependencyProperty ContentProperty =
			DependencyProperty.Register("Content", typeof(FrameworkElement), typeof(BoxItem), new UIPropertyMetadata(null));
		public static readonly DependencyProperty IsActiveProperty =
			DependencyProperty.Register("IsActive", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty ProgressProperty =
			DependencyProperty.Register("Progress", typeof(int), typeof(BoxItem), new UIPropertyMetadata(0));
		public static readonly DependencyProperty ShowProgressProperty =
			DependencyProperty.Register("ShowProgress", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsHighlightedProperty =
			DependencyProperty.Register("IsHighlighted", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsChangedProperty =
			DependencyProperty.Register("IsChanged", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsMouseDraggedOverProperty =
			DependencyProperty.Register("IsMouseDraggedOver", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsLocallyActiveProperty =
			DependencyProperty.Register("IsLocallyActive", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsClosableProperty =
			DependencyProperty.Register("IsClosable", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(true));
		public static readonly DependencyProperty SubTitleProperty =
			DependencyProperty.Register("SubTitle", typeof(string), typeof(BoxItem), new UIPropertyMetadata(null));
		internal static readonly DependencyProperty IsAutoHideOpenProperty =
			DependencyProperty.Register("IsAutoHideOpen", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(false));
		public static readonly DependencyProperty IsAutoHideAllowedProperty =
			DependencyProperty.Register("IsAutoHideAllowed", typeof(bool), typeof(BoxItem), new UIPropertyMetadata(true));
		public static readonly DependencyProperty ToolTipProperty =
			DependencyProperty.Register("ToolTip", typeof(string), typeof(BoxItem), new UIPropertyMetadata(null));

		#endregion

		#region Events

		/// <summary>
		/// Event fired when the BoxItem is about to be closed.
		/// </summary>
		/// <remarks>
		/// <see cref="System.ComponentModel.CancelEventArgs.Cancel"/> property
		/// can be used to cancel closing of the BoxItem.
		/// </remarks>
		public event CancelEventHandler Closing;

		/// <summary>
		/// Event signalling that the BoxItem has been closed eventually.
		/// </summary>
		public event EventHandler Closed;

		/// <summary>
		/// Event that is fired when the direction of the BoxItem has changed.
		/// </summary>
		public event EventHandler<DirectionChangedEventArgs> DirectionChanged;

		/// <summary>
		/// Event signalling that the item has been moved to auto-hide area.
		/// </summary>
		public event EventHandler MovedToAutoHideArea;

		/// <summary>
		/// Event signalling that the item has been undocked as a floating window.
		/// </summary>
		public event EventHandler Floating;

		/// <summary>
		/// Event that is fired when the parent <see cref="AWZhome.awzBoxes.Box"/> of the box item is changed.
		/// </summary>
		public event EventHandler<ParentChangedEventArgs<Box>> ParentBoxChanged;

		/// <summary>
		/// Fired when the user request the context menu for a <see cref="AWZhome.awzBoxes.BoxItem"/>.
		/// </summary>
		public event EventHandler<ContextMenuRequestedEventArgs> ContextMenuRequested;

		#endregion

		public BoxItem()
		{
			this.AllowedDockAreas = BoxItemDockDirection.DockableEverywhere;
			_direction = BoxItemDockDirection.NotDocking;
			this.PopupSize = Double.NaN;
			this.AutoHideStoredBoxAreaSize = Double.NaN;
			this.AutoHideStoredBoxLineSize = Double.NaN;
			this.AutoHideStoredBoxSize = Double.NaN;

			this.IsRestored = true;
		}

		/// <summary>
		/// Gets/sets the content control displayed within the BoxItem.
		/// </summary>
		public FrameworkElement Content
		{
			get
			{
				return (FrameworkElement) GetValue(ContentProperty);
			}
			set
			{
				SetValue(ContentProperty, value);
			}
		}

		/// <summary>
		/// Gets/sets the icon shown in the tab header for the BoxItem.
		/// </summary>
		public System.Windows.Media.ImageSource Icon
		{
			get
			{
				return (System.Windows.Media.ImageSource) GetValue(IconProperty);
			}
			set
			{
				SetValue(IconProperty, value);
			}
		}

		/// <summary>
		/// Gets/sets the title of the BoxItem, displayed in its tab header.
		/// </summary>
		public string Title
		{
			get
			{
				return (string) GetValue(TitleProperty);
			}
			set
			{
				SetValue(TitleProperty, value);
			}
		}

		/// <summary>
		/// Gets/sets the tool tip text shown when mouse cursor is over the tab header.
		/// </summary>
		public string ToolTip
		{
			get
			{
				return (string) GetValue(ToolTipProperty);
			}
			set
			{
				SetValue(ToolTipProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem is active within the whole BoxArea.
		/// </summary>
		public bool IsActive
		{
			get
			{
				return (bool) GetValue(IsActiveProperty);
			}
			set
			{
				SetValue(IsActiveProperty, value);
			}
		}

		/// <summary>
		/// Determines whether to show a progress bar in the BoxItem's tab header.
		/// </summary>
		public bool ShowProgress
		{
			get
			{
				return (bool) GetValue(ShowProgressProperty);
			}
			set
			{
				SetValue(ShowProgressProperty, value);
			}
		}

		/// <summary>
		/// Gets/sets the progress value (in percents 0-100) shown in
		/// the BoxItem's tab header.
		/// </summary>
		public int Progress
		{
			get
			{
				return (int) GetValue(ProgressProperty);
			}
			set
			{
				SetValue(ProgressProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem should be shown as changed.
		/// </summary>
		public bool IsChanged
		{
			get
			{
				return (bool) GetValue(IsChangedProperty);
			}
			set
			{
				SetValue(IsChangedProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem should be highlighted.
		/// </summary>
		public bool IsHighlighted
		{
			get
			{
				return (bool) GetValue(IsHighlightedProperty);
			}
			set
			{
				SetValue(IsHighlightedProperty, value);
			}
		}

		/// <summary>
		/// Determines whether another BoxItem is dragged over current BoxItem's tab header.
		/// </summary>
		public bool IsMouseDraggedOver
		{
			get
			{
				return (bool) GetValue(IsMouseDraggedOverProperty);
			}
			set
			{
				SetValue(IsMouseDraggedOverProperty, value);
			}
		}

		/// <summary>
		/// Determines whether this BoxItem is active within its parent
		/// <see cref="AWZhome.awzBoxes.Box"/>.
		/// </summary>
		public bool IsLocallyActive
		{
			get
			{
				return (bool) GetValue(IsLocallyActiveProperty);
			}
			set
			{
				SetValue(IsLocallyActiveProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem's auto-hide popup is currently open.
		/// </summary>
		internal bool IsAutoHideOpen
		{
			get
			{
				return (bool) GetValue(IsAutoHideOpenProperty);
			}
			set
			{
				SetValue(IsAutoHideOpenProperty, value);
			}
		}

		/// <summary>
		/// Gets/sets the sub-title for this BoxItem, showing an additional description
		/// of the contents.
		/// </summary>
		public string SubTitle
		{
			get
			{
				return (string) GetValue(SubTitleProperty);
			}
			set
			{
				SetValue(SubTitleProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem may be closed by user.
		/// This does not prevent the code from closing or moving it!
		/// </summary>
		public bool IsClosable
		{
			get
			{
				return (bool) GetValue(IsClosableProperty);
			}
			set
			{
				SetValue(IsClosableProperty, value);
			}
		}

		/// <summary>
		/// Determines whether the BoxItem may be auto-hidden by user.
		/// </summary>
		public bool IsAutoHideAllowed
		{
			get
			{
				return (bool) GetValue(IsAutoHideAllowedProperty);
			}
			set
			{
				SetValue(IsAutoHideAllowedProperty, value);
			}
		}

		/// <summary>
		/// Specifies if the BoxItem should be restored when it was
		/// open after last application exit.
		/// </summary>
		public bool IsRestored
		{
			get;
			set;
		}

		/// <summary>
		/// Sets the areas where this BoxItem is allowed to be docked to.
		/// The values of <see cref="AWZhome.awzBoxes.BoxItemDockDirection"/>
		/// enumeration can be combined using the OR bit operator.
		/// </summary>
		public BoxItemDockDirection AllowedDockAreas
		{
			get;
			set;
		}

		/// <summary>
		/// Gets/sets the internal name of the BoxItem.
		/// </summary>
		public string Name
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the direction of the BoxItem.
		/// </summary>
		public BoxItemDockDirection Direction
		{
			get
			{
				return _direction;
			}
			set
			{
				switch (value)
				{
					case BoxItemDockDirection.DockableEverywhere:
						// Invalid value!
						throw new InvalidOperationException("Invalid direction for a BoxItem.");
					default:
						break;
				}

				// When this value is changed, re-dock the BoxItem
				if (_direction != value)
				{
					BoxWindowContainer boxWindowContainer = this.ParentBoxWindowContainer;
					if (boxWindowContainer != null)
					{
						switch (value)
						{
							case BoxItemDockDirection.NotDocking:
								this.Undock();
								break;

							case BoxItemDockDirection.DockTop:
								this.Redock(boxWindowContainer.TopBoxArea);
								break;

							case BoxItemDockDirection.DockBottom:
								this.Redock(boxWindowContainer.BottomBoxArea);
								break;

							case BoxItemDockDirection.DockLeft:
								this.Redock(boxWindowContainer.LeftBoxArea);
								break;

							case BoxItemDockDirection.DockRight:
								this.Redock(boxWindowContainer.RightBoxArea);
								break;

							case BoxItemDockDirection.DockInnerArea:
								if ((boxWindowContainer.InnerAreaControl as BoxArea) != null)
								{
									this.Redock((BoxArea) boxWindowContainer.InnerAreaControl);
								}
								break;

							case BoxItemDockDirection.Floating:
								BoxWindowContainer parentBoxWindowContainer = this.ParentBoxWindowContainer;
								bool gotBoxRect = false;
								Point topLeftCorner = new Point();
								Point bottomRightCorner = new Point();
								if (_parentBox != null)
								{
									// Get screen position and size of parent Box
									topLeftCorner = PointTransformer.ConvertToScreen(new Point(0, 0), _parentBox);
									bottomRightCorner = PointTransformer.ConvertToScreen(
									   new Point(_parentBox.ActualWidth, _parentBox.ActualHeight), _parentBox);

									gotBoxRect = true;
								}

								this.Undock();
								FloatingWindow floatingWindow = new FloatingWindow(parentBoxWindowContainer, this);
								if (gotBoxRect)
								{
									// Set size and position of FloatingWindow to actual size and position of former parent Box
									floatingWindow.Top = topLeftCorner.Y;
									floatingWindow.Left = topLeftCorner.X;
									floatingWindow.Height = bottomRightCorner.Y - topLeftCorner.Y;
									floatingWindow.Width = bottomRightCorner.X - topLeftCorner.X;
								}
								else
								{
									// Center the FloatingWindow on the screen
									floatingWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
								}

								floatingWindow.Show();
								break;

							default:
								break;
						}
					}
				}
				this._Direction = value;
			}
		}

		internal BoxItemDockDirection _Direction
		{
			set
			{
				BoxItemDockDirection oldDirection = _direction;
				_direction = value;
				this.OnDirectionChanged(oldDirection, value);
			}
		}

		/// <summary>
		/// Gets/sets the value of the activity counter, which determines the sort
		/// position of this BoxItem in window selection popup.
		/// </summary>
		internal UInt64 ActivityCount
		{
			get;
			set;
		}

		/// <summary>
		/// Retrieves the <see cref="AWZhome.awzBoxes.Box"/> that contains the current box item.
		/// </summary>
		public Box ParentBox
		{
			get
			{
				return _parentBox;
			}
			internal set
			{
				Box _oldParentBox = _parentBox;
				_parentBox = value;
				if (this.ParentBoxChanged != null)
				{
					this.ParentBoxChanged(this, new ParentChangedEventArgs<Box>(_oldParentBox, value));
				}
			}
		}

		/// <summary>
		/// Retrieves the <see cref="AWZhome.awzBoxes.AutoHiddenBox"/> that
		/// contains the current box item, if in auto-hidden state.
		/// </summary>
		public AutoHiddenBox ParentAutoHiddenBox
		{
			get
			{
				return _parentAutoHiddenBox;
			}
			internal set
			{
				_parentAutoHiddenBox = value;
				if (value != null)
				{
					// Fire MovedToAutoHideArea
					this.OnMovedToAutoHideArea();
				}
			}
		}

		/// <summary>
		/// Retrieves the <see cref="AWZhome.awzBoxes.FloatingWindow"/> that
		/// containes the current box item, if in floating state.
		/// </summary>
		public FloatingWindow ParentFloatingWindow
		{
			get
			{
				return _parentFloatingWindow;
			}
			internal set
			{
				_parentFloatingWindow = value;
				if (value != null)
				{
					// Fire Floating event
					this.OnFloating();
				}
			}
		}

		/// <summary>
		/// Stores the size (height or width) of the <see cref="AWZhome.awzBoxes.BoxArea"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal double AutoHideStoredBoxAreaSize
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the size (height or width) of the <see cref="AWZhome.awzBoxes.BoxLine"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal double AutoHideStoredBoxLineSize
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the size (height or width) of the <see cref="AWZhome.awzBoxes.Box"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal double AutoHideStoredBoxSize
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the index of the <see cref="AWZhome.awzBoxes.BoxLine"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal int AutoHideStoredBoxLineIndex
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the index of the <see cref="AWZhome.awzBoxes.Box"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal int AutoHideStoredBoxIndex
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the index of the <see cref="AWZhome.awzBoxes.BoxLine"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal int AutoHideStoredItemIndex
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the ID of the <see cref="AWZhome.awzBoxes.BoxLine"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal int? AutoHideStoredBoxLineID
		{
			get;
			set;
		}

		/// <summary>
		/// Stores the ID of the <see cref="AWZhome.awzBoxes.Box"/>,
		/// before the BoxItem was moved to auto-hide area.
		/// </summary>
		internal int? AutoHideStoredBoxID
		{
			get;
			set;
		}

		/// <summary>
		/// Retrieves the <see cref="AWZhome.awzBoxes.BoxWindowContainer"/> that contains the current box item.
		/// </summary>
		public BoxWindowContainer ParentBoxWindowContainer
		{
			get
			{
				// Try to get the BoxWindowContainer from a parent Box (and the hiearchy above it)
				Box parentBox;
				if ((parentBox = this.ParentBox) != null)
				{
					BoxLine parentBoxLine;
					if ((parentBoxLine = parentBox.ParentBoxLine) != null)
					{
						BoxArea parentBoxArea;
						if ((parentBoxArea = parentBoxLine.ParentBoxArea) != null)
						{
							return parentBoxArea.ParentBoxWindowContainer;
						}
					}
				}

				// Try to get the BoxWindowContainer from a parent FloatingWindow
				if (this.ParentFloatingWindow != null)
				{
					return this.ParentFloatingWindow.ParentBoxWindowContainer;
				}

				return null;
			}
		}

		/// <summary>
		/// Gets/sets the size of the auto-hide popup shown for this BoxItem.
		/// </summary>
		public double PopupSize
		{
			get;
			set;
		}

		/// <summary>
		/// Undocks the <see cref="AWZhome.awzBoxes.BoxItem"/> from its container.
		/// </summary>
		/// <remarks>
		/// In opposite to <see cref="AWZhome.awzBoxes.BoxItem.Close"/> method this method
		/// doesn't raise any closing events.
		/// </remarks>
		public void Undock()
		{
			if (this.ParentBox != null)
			{
				this.ParentBox.Items.Remove(this);
			}
			else if (this.ParentAutoHiddenBox != null)
			{
				this.ParentAutoHiddenBox.Items.Remove(this);
			}
			else if (this.ParentFloatingWindow != null)
			{
				this.ParentFloatingWindow.Close();
			}
			else
			{
				this._Direction = BoxItemDockDirection.NotDocking;
			}
		}

		/// <summary>
		/// Closes current BoxItem.
		/// </summary>
		public void Close()
		{
			if (this.ParentBox != null)
			{
				if (this.OnClosing())
				{
					BoxWindowContainer container = this.ParentBoxWindowContainer;
					if (container != null)
					{
						container.SaveLayout(this);
					}
					this.ParentBox.Items.Remove(this);
					this.OnClosed();
				}
			}
			else if (this.ParentAutoHiddenBox != null)
			{
				if (this.OnClosing())
				{
					BoxWindowContainer container = this.ParentBoxWindowContainer;
					if (container != null)
					{
						container.SaveLayout(this);
					}
					this.ParentAutoHiddenBox.Items.Remove(this);
					this.OnClosed();
				}
			}
			else if (this.ParentFloatingWindow != null)
			{
				if (this.OnClosing())
				{
					BoxWindowContainer container = this.ParentBoxWindowContainer;
					if (container != null)
					{
						container.SaveLayout(this);
					}
					this.ParentFloatingWindow.Close();
					this.OnClosed();
				}
			}
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.Closing"/> event.
		/// </summary>
		/// <returns><c>True</c>, if the BoxItem is allowed to be closed, <c>false</c> otherwise.</returns>
		protected bool OnClosing()
		{
			bool closingCancelled = false;
			if (this.Closing != null)
			{
				CancelEventArgs cancelEventArgs = new CancelEventArgs(false);
				this.Closing(this, cancelEventArgs);
				closingCancelled = cancelEventArgs.Cancel;
			}

			return !closingCancelled;
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.Closed"/> event.
		/// </summary>
		protected void OnClosed()
		{
			if (this.Closed != null)
			{
				this.Closed(this, new EventArgs());
			}
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.DirectionChanged"/> event.
		/// </summary>
		/// <param name="oldDirection">Old direction value.</param>
		/// <param name="newDirection">New direction value.</param>
		protected void OnDirectionChanged(BoxItemDockDirection oldDirection, BoxItemDockDirection newDirection)
		{
			if (this.DirectionChanged != null)
			{
				this.DirectionChanged(this, new DirectionChangedEventArgs(oldDirection, newDirection));
			}
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.MovedToAutoHideArea"/> event.
		/// </summary>
		protected void OnMovedToAutoHideArea()
		{
			if (this.MovedToAutoHideArea != null)
			{
				this.MovedToAutoHideArea(this, new EventArgs());
			}
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.Floating"/> event.
		/// </summary>
		protected void OnFloating()
		{
			if (this.Floating != null)
			{
				this.Floating(this, new EventArgs());
			}
		}

		/// <summary>
		/// Fires the <see cref="AWZhome.awzBoxes.BoxItem.ContextMenuRequested"/> event.
		/// <param name="source">The source that the context menu has been requested for.</param>
		/// </summary>
		internal void OnContextMenuRequested(ContextMenuRequestSource source)
		{
			if (this.ContextMenuRequested != null)
			{
				this.ContextMenuRequested(this, new ContextMenuRequestedEventArgs(source));
			}
		}

		/// <summary>
		/// Moves the current <see cref="AWZhome.awzBoxes.BoxItem"/> to the given
		/// <see cref="AWZhome.awzBoxes.BoxArea"/>.
		/// </summary>
		/// <param name="targetBoxArea">The <see cref="AWZhome.awzBoxes.BoxArea"/> to move the item to.</param>
		internal void Redock(BoxArea targetBoxArea)
		{
			if ((targetBoxArea != null) && (targetBoxArea.CanContainBoxItem(this)))
			{
				this.Undock();
				BoxLine boxLine = null;
				if (targetBoxArea.BoxLines.Count == 0)
				{
					boxLine = new BoxLine();
					targetBoxArea.BoxLines.Add(boxLine);
				}
				else
				{
					boxLine = targetBoxArea.BoxLines[0];
				}
				Box box = null;
				if (boxLine.Boxes.Count == 0)
				{
					box = new Box();
					boxLine.Boxes.Add(box);
				}
				else
				{
					box = boxLine.Boxes[0];
				}
				box.Items.Add(this);
			}
		}

		protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
		{
			base.OnPropertyChanged(e);

			if ((e.Property == BoxItem.IsActiveProperty) || (e.Property == BoxItem.IsLocallyActiveProperty))
			{
				// IsActive property has been changed
				if ((bool) e.NewValue)
				{
					Box box = this.ParentBox;
					if (box != null)
					{
						BoxLine line = box.ParentBoxLine;
						if (line != null)
						{
							BoxArea area = line.ParentBoxArea;
							if ((area != null) && (area.ActiveBoxItem != this))
							{
								area.ActiveBoxItem = this;
							}
						}
					}

					if ((e.Property == BoxItem.IsActiveProperty) && (this.IsActive != this.IsLocallyActive))
					{
						this.IsLocallyActive = true;
					}
				}
			}
		}
	}
}
